package models

import (
	"errors"
	"fmt"
	"go_pure_admin_api/dto"
	"go_pure_admin_api/global"
	"go_pure_admin_api/utils"
	"gorm.io/gorm"
	"time"
)

// Users 用户表
type Users struct {
	gorm.Model
	Nickname      string       `gorm:"comment:姓名;size:50" json:"nickname" validate:"required" form:"nickname"`
	Username      string       `gorm:"comment:登录名;unique;size:50" json:"username" validate:"required" form:"username"`
	Password      string       `gorm:"comment:密码;size:255" json:"-" validate:"required" form:"password"`
	Roles         []Roles      `gorm:"many2many:users_roles;" json:"roles"`
	DepartmentID  *uint        `gorm:"comment:部门ID;" json:"department_id" form:"department_id"`
	Department    *Departments `gorm:"foreignKey:DepartmentID;constraint:OnDelete:SET NULL" json:"department"`
	Sex           uint8        `gorm:"comment:性别 0:女,1:男" json:"sex" form:"sex"`
	Age           uint8        `gorm:"comment:年龄" json:"age" form:"age"`
	Phone         string       `gorm:"comment:手机号;unique;size:20" json:"phone" validate:"required,customValidate" form:"phone"`
	Avatar        string       `gorm:"comment:头像;size:500" json:"avatar" form:"avatar"`
	Email         string       `gorm:"comment:邮箱;size:100" json:"email" validate:"required,email" form:"email"`
	Description   string       `gorm:"comment:描述;size:500" json:"description" form:"description"`
	ClientIp      string       `gorm:"comment:客户端Ip;size:50" json:"client_ip" form:"client_ip"`
	Status        int8         `gorm:"comment:状态 0:禁用 1:启用;default:1" json:"status" form:"status"`
	CreatedUser   *Users       `gorm:"foreignKey:CreatedUserID;constraint:OnUpdate:CASCADE,OnDelete:SET NULL" json:"created_user" form:"created_user"`
	CreatedUserID *uint        `json:"created_user_id"`
	LoginTime     *time.Time   `gorm:"comment:登录时间" json:"loginTime" form:"loginTime"`
	LoginOutTime  *time.Time   `gorm:"comment:登出时间" json:"loginOutTime" form:"loginOutTime"`
	DeviceInfo    string       `gorm:"comment:设备信息;size:500" json:"deviceInfo" form:"deviceInfo"`
}

func init() {
	err := global.DB.AutoMigrate(&Users{})
	if err != nil {
		global.Logger.Errorf("自动迁移用户表发生错误: %v", err)
		return
	}
}
func (u *Users) BeforeDelete(*gorm.DB) error {
	if u.Username == "admin" {
		return fmt.Errorf("不能对超级管理员用户进行删除操作")
	}
	return nil
}

// QueryUserByName 根据用户名查询用户
func (u *Users) QueryUserByName(username string) error {
	err := global.DB.Preload("Roles").Find(u, "username = ?", username).Error
	if err != nil {
		return err
	}
	return nil
}

// GetMenusRouterThereByLoginName 根据登录用户名获取用户菜单树
func (u *Users) GetMenusRouterThereByLoginName(username string) (menusRoutes []*dto.MenuDto, err error) {
	menus, err := u.GetMenusByLoginName(username)
	if err != nil {
		return nil, err
	}
	menuRoute := &dto.MenuDto{}
	return BuildMenuTree(menuRoute, menus), nil
}

// GetMenusByLoginName 根据登录用户名获取用户菜单
func (u *Users) GetMenusByLoginName(username string) (menus []Menus, err error) {
	// 判断是否有超级管理员角色
	isAdmin, err := u.IsAdminByLoginName(username)
	if err != nil {
		return nil, err
	}
	if isAdmin {
		allMenus, err := GetAllMenus()
		if err != nil {
			return nil, err
		}
		return allMenus, nil
	}
	if err := global.DB.Preload("Roles.Menus", "type = ?", 0, func(db *gorm.DB) *gorm.DB {
		return db.Order("`rank` ASC")
	}).Find(u, "username = ?", username).Error; err != nil {
		return nil, err
	}
	for _, role := range u.Roles {
		menus = append(menus, role.Menus...)
	}
	return menus, nil
}

// IsAdminByLoginName 查询是否有管理员角色
func (u *Users) IsAdminByLoginName(username string) (bool, error) {
	err := global.DB.Preload("Roles").Find(u, "username = ?", username).Error
	if err != nil {
		return false, err
	}
	for _, role := range u.Roles {
		if role.Key == "root" {
			return true, nil
		}
	}
	return false, nil
}

// GetRoleKeys 查询用户角色
func (u *Users) GetRoleKeys() (keys []string) {
	if u.Roles == nil {
		return
	}
	for _, v := range u.Roles {
		keys = append(keys, v.Key)
	}
	return
}

func GetAllUserList() (users []Users, err error) {
	//获取所有用户
	err = global.DB.Find(&users).Error
	return
}

func (u *Users) GetUserButtonPermissions(username string) (buttonPermissions []string, err error) {
	// 判断是否有超级管理员角色
	isAdmin, err := u.IsAdminByLoginName(username)
	if err != nil {
		return nil, err
	}
	if isAdmin {
		return []string{"*:*:*"}, nil
	}

	// 查询用户及其角色和菜单权限
	if err := global.DB.Preload("Roles.Menus", "type = ?", 1).Find(u, "username = ?", username).Error; err != nil {
		return nil, err
	}

	// 使用 map 来去重
	permissionMap := make(map[string]bool)

	for _, role := range u.Roles {
		for _, menu := range role.Menus {
			// 检查权限字段是否为空
			if menu.Auths != "" {
				permissionMap[menu.Auths] = true
			}
		}
	}

	// 将 map 中的权限转换为 slice
	buttonPermissions = make([]string, 0, len(permissionMap))
	for permission := range permissionMap {
		buttonPermissions = append(buttonPermissions, permission)
	}

	return buttonPermissions, nil
}
func (u *Users) GetUserList(data dto.GetUserListDto) (userList []Users, total int64, err error) {
	qs := global.DB.Model(u)

	if data.UserInfo != "" {
		// 模糊查询
		qs = qs.Where("nickname like ? or username like ? or phone like ? or email like ?",
			"%"+data.UserInfo+"%", "%"+data.UserInfo+"%", "%"+data.UserInfo+"%", "%"+data.UserInfo+"%")
	}

	if data.Status != "" {
		qs = qs.Where("status = ?", data.Status)
	}

	if data.DeptId != "" {
		// 使用CTE递归查询获取部门及其所有子部门的ID
		cteSQL := `
        WITH RECURSIVE dept_tree AS (
            SELECT id FROM departments WHERE id = ?
            UNION ALL
            SELECT d.id FROM departments d
            INNER JOIN dept_tree dt ON d.parent_id = dt.id
        )`

		// 子查询获取所有相关部门ID
		subQuery := global.DB.Raw(cteSQL+" SELECT id FROM dept_tree", data.DeptId)
		qs = qs.Where("department_id IN (?)", subQuery)
	}

	// 先计算总数
	if err := qs.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 查询用户列表
	if err := qs.Preload("Department").
		Offset((data.CurrentPage - 1) * data.PageSize).
		Limit(data.PageSize).
		Find(&userList).Error; err != nil {
		return nil, 0, err
	}

	return userList, total, nil
}

func (u *Users) CreateUser(data dto.CreateUserDto) error {
	u.Username = data.Username
	u.Nickname = data.Nickname
	u.Password = data.Password
	u.Email = data.Email
	u.Phone = data.Phone
	u.Sex = data.Sex
	u.Status = data.Status
	if data.DeptId != 0 {
		u.DepartmentID = &data.DeptId
	}
	return global.DB.Create(u).Error
}

func (u *Users) UpdateUser(data dto.UpdateUserDto) error {
	err := global.DB.Find(u, data.ID).Error
	if err != nil {
		return err
	}
	u.Status = data.Status
	u.Username = data.Username
	u.Nickname = data.Nickname
	u.Email = data.Email
	u.Phone = data.Phone
	u.Sex = data.Sex
	if data.DeptId != 0 {
		u.DepartmentID = &data.DeptId
	}
	return global.DB.Save(u).Error
}

func (u *Users) DeleteUser(data dto.DeleteUserDto) error {
	if err := global.DB.Find(u, data.ID).Error; err != nil {
		return err
	}
	// 开启自动事务
	if err := global.DB.Transaction(func(tx *gorm.DB) error {
		// 清空用户的casbin权限
		if utils.GetUserRoleByLoginName(u.Username) {
			role, err := utils.RemoveUserRole(u.Username)
			if err != nil {
				return err
			}
			if !role {
				return errors.New("删除权限失败")
			}
		}
		// 清空用户角色关联
		if err := tx.Model(u).Association("Roles").Clear(); err != nil {
			return err
		}
		// 删除用户
		if err := tx.Delete(u).Error; err != nil {
			return err
		}
		return nil
	}); err != nil {
		return err
	}
	return nil
}

func (u *Users) GetUserRoleIds(data dto.GetUserRoleIdsDto) (roleIds []uint, err error) {
	err = global.DB.
		Model(&Roles{}).
		Joins("JOIN users_roles ON users_roles.roles_id = roles.id").
		Where("users_roles.users_id = ?", data.ID).
		Pluck("roles.id", &roleIds).
		Error
	return
}
func (u *Users) UpdatePassword(data dto.UpdatePasswordDto) (err error) {
	return global.DB.Model(u).Where("id = ?", data.ID).Update("password", data.NewPassword).Error
}

func (u *Users) UpdateUserRole(data dto.UpdateUserRoleDto) (err error) {
	var roles []Roles
	tx := global.DB.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
			panic(r)
		}
	}()

	// 查找用户
	if err := tx.First(u, data.ID).Error; err != nil {
		tx.Rollback()
		return err
	}
	// 如果角色ID为空
	if len(data.RoleIds) == 0 {
		if err := tx.Model(u).Association("Roles").Clear(); err != nil {
			tx.Rollback()
			return err
		}
		if utils.GetUserRoleByLoginName(u.Username) { // 建议重命名这个函数
			// 删除现有权限
			if success, err := utils.RemoveUserRole(u.Username); err != nil || !success {
				tx.Rollback()
				if err != nil {
					return err
				}
				return errors.New("删除权限失败")
			}
		}
	} else {

		// 获取新角色
		err = tx.Find(&roles, data.RoleIds).Error
		if err != nil {
			tx.Rollback()
			return err
		}

		// 更新数据库中的角色关联
		if err := tx.Model(u).Association("Roles").Replace(roles); err != nil {
			tx.Rollback()
			return err
		}

		// 更新Casbin权限
		if utils.GetUserRoleByLoginName(u.Username) { // 建议重命名这个函数
			// 删除现有权限
			if success, err := utils.RemoveUserRole(u.Username); err != nil || !success {
				tx.Rollback()
				if err != nil {
					return err
				}
				return errors.New("删除权限失败")
			}
		}

		// 添加新权限
		for _, role := range roles {
			if success, err := utils.AddUserRole(u.Username, role.Key); err != nil || !success {
				tx.Rollback()
				if err != nil {
					return err
				}
				return errors.New("添加权限失败")
			}
		}
	}
	// 提交事务
	if err := tx.Commit().Error; err != nil {
		return err
	}
	return nil
}

func BatchDeleteUser(data dto.BatchDeleteUserDto) error {
	var userList []Users
	global.DB.Where("id IN ?", data.IDs).Find(&userList)
	// 开启自动事务
	if err := global.DB.Transaction(func(tx *gorm.DB) error {
		// 清空用户角色关联
		if err := tx.Model(&userList).Association("Roles").Clear(); err != nil {
			return err
		}
		// 删除用户
		if err := tx.Delete(&userList).Error; err != nil {
			return err
		}
		// 删除用户的casbin权限
		for _, user := range userList {
			if utils.GetUserRoleByLoginName(user.Username) {
				role, err := utils.RemoveUserRole(user.Username)
				if err != nil {
					return err
				}
				if !role {
					return errors.New("删除权限失败")
				}
			}
		}
		return nil
	}); err != nil {
		return err
	}
	return nil
}

func (u *Users) UpdateAvatar(path string) error {
	// 更新用户之前删除上传的图片
	if u.Avatar != "" {
		if err := utils.DeleteAvatar(u.Avatar); err != nil {
			return err
		}
	}
	// 更新头像
	if err := global.DB.Model(u).Update("avatar", path).Error; err != nil {
		return err
	}
	return nil
}

func UpdateUserInfo(data dto.UpdateUserInfoDto) error {
	if err := global.DB.Model(&Users{}).Where("id", data.ID).Updates(map[string]interface{}{
		"description": data.Description,
		"email":       data.Email,
		"nickname":    data.Nickname,
		"phone":       data.Phone,
	}).Error; err != nil {
		return err
	}
	return nil
}

func UpdateUserPassword(data dto.UpdateUserPasswordDto) error {
	var user Users
	err := global.DB.Find(&user, data.ID).Error
	if err != nil {
		return err
	}
	HexPassword, err := utils.HashPassword(data.NewPassword)
	if err != nil {
		return err
	}
	if utils.CheckPassword(data.CurrentPassword, user.Password) {
		return global.DB.Model(&Users{}).Where("id", data.ID).Update("password", HexPassword).Error
	} else {
		return errors.New("当前密码错误")
	}
}
